package com.winner.data.util.excel;

import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Set;

import javax.servlet.http.HttpServletResponse;

import org.apache.poi.ss.usermodel.BorderStyle;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.usermodel.IndexedColors;
import org.apache.poi.ss.usermodel.VerticalAlignment;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.write.metadata.style.WriteCellStyle;
import com.alibaba.excel.write.metadata.style.WriteFont;
import com.alibaba.excel.write.style.HorizontalCellStyleStrategy;

import cn.hutool.core.collection.ListUtil;
import lombok.SneakyThrows;

/**
 * easyExcel导出工具类
 *
 * @author wangxinle5
 * @since 2023-04-18
 */
public class EasyExcelUtil {

    /**
     * 普通的导出(FreezeRowColHandler固定了表头) 可以传参 WriteHandler writeHandler
     *
     * @param list 导出数据集合
     * @param clazz 类型
     * @param fileName 文件名称
     * @param response HttpServletResponse
     */
    @SneakyThrows
    public static <T> void writeExcel(List<T> list, Class<T> clazz, String fileName, HttpServletResponse response) {
        setResponse(response, fileName);
        EasyExcel.write(response.getOutputStream(), clazz)
            // .registerWriteHandler自定义策略(支持扩展多个)
            .registerWriteHandler(getStyleStrategy()).registerWriteHandler(new CustomWidthStyleStrategy())
            .registerWriteHandler(new FreezeRowColHandler(FreezeRowColConstant.TEST_ONE)).sheet("Sheet1").doWrite(list);
    }

    /**
     * 标题可变的excel导出(固定第一行表头)
     *
     * @param sheetData sheetData
     * @param fixHeaderList fixHeaderList
     * @param dynamicHeaderList dynamicHeaderList
     * @param orangeSet orangeSet
     * @param redSet redSet
     * @param fileName fileName
     * @param response response
     */
    @SneakyThrows
    public static void writeExcelBySheetData(List<List<Object>> sheetData, ArrayList<String> fixHeaderList,
        ArrayList<String> dynamicHeaderList, Set<String> orangeSet, Set<String> redSet, String fileName,
        HttpServletResponse response) {
        setResponse(response, fileName);
        EasyExcel.write(response.getOutputStream()).head(initDynamicHeader(fixHeaderList, dynamicHeaderList))
            // 基础的样式
            .registerWriteHandler(getStyleStrategy())
            .registerWriteHandler(
                new CustomCellWriteHandler(IndexedColors.ORANGE.index, IndexedColors.WHITE.index, orangeSet))
            .registerWriteHandler(
                new CustomCellWriteHandler(IndexedColors.RED.index, IndexedColors.WHITE.index, redSet))
            .registerWriteHandler(new FreezeRowColHandler(FreezeRowColConstant.TEST_ONE))
            .registerWriteHandler(new CustomWidthStyleStrategy()).sheet("Sheet1").doWrite(sheetData);
    }

    /**
     * 导出excel到D盘盘符下
     *
     * @param sheetData sheetData
     * @param fixHeaderList fixHeaderList
     * @param fileName fileName
     */
    @SneakyThrows
    public static void writeExcelBySheetData(List<List<Object>> sheetData, List<String> fixHeaderList,
        String fileName) {
        EasyExcel.write(fileName).head(initDynamicHeader(fixHeaderList))
            // 基础的样式
            .registerWriteHandler(getStyleStrategy()).registerWriteHandler(new CustomWidthStyleStrategy())
            .sheet("Sheet1").doWrite(sheetData);
    }

    /**
     * 构造动态表头, 这里入参我们传fixHeaderList, dynamicHeaderList
     *
     * @param dynamicHeaderList 动态表头参数实际是 List<String>[]
     * @return 结果
     */
    private static List<List<String>> initDynamicHeader(List<String>... dynamicHeaderList) {
        // 自定义标题
        List<List<String>> customHeaders = new ArrayList<>();
        Arrays.stream(dynamicHeaderList).forEach(a -> {
            a.forEach(b -> customHeaders.add(ListUtil.toList(b)));
        });
        System.out.println(customHeaders);
        return customHeaders;
    }

    /**
     * 设置响应结果
     *
     * @param response 响应结果对象
     * @param rawFileName 文件名
     */
    @SneakyThrows
    private static void setResponse(HttpServletResponse response, String rawFileName) {
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        response.setCharacterEncoding("utf-8");
        String fileName = URLEncoder.encode(rawFileName, "UTF-8").replaceAll("\\+", "%20");
        response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");
    }

    /**
     * 设置excel样式 给标题 和 内容 一个基础的样式
     */
    public static HorizontalCellStyleStrategy getStyleStrategy() {
        // 头的策略 样式调整
        WriteCellStyle headWriteCellStyle = new WriteCellStyle();
        // 头背景 浅绿
        headWriteCellStyle.setFillForegroundColor(IndexedColors.CORNFLOWER_BLUE.getIndex());
        WriteFont headWriteFont = new WriteFont();
        // 头字号
        headWriteFont.setFontHeightInPoints((short)15);
        // 字体样式
        headWriteFont.setFontName("宋体");
        headWriteCellStyle.setWriteFont(headWriteFont);
        // 自动换行
        headWriteCellStyle.setWrapped(Boolean.FALSE);
        // 设置细边框
        headWriteCellStyle.setBorderBottom(BorderStyle.THIN);
        headWriteCellStyle.setBorderLeft(BorderStyle.THIN);
        headWriteCellStyle.setBorderRight(BorderStyle.THIN);
        headWriteCellStyle.setBorderTop(BorderStyle.THIN);
        // 设置边框颜色 25灰度
        headWriteCellStyle.setBottomBorderColor(IndexedColors.BLACK.getIndex());
        headWriteCellStyle.setTopBorderColor(IndexedColors.BLACK.getIndex());
        headWriteCellStyle.setLeftBorderColor(IndexedColors.BLACK.getIndex());
        headWriteCellStyle.setRightBorderColor(IndexedColors.BLACK.getIndex());
        // 水平对齐方式
        headWriteCellStyle.setHorizontalAlignment(HorizontalAlignment.CENTER);
        // 垂直对齐方式
        headWriteCellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
        // 内容的策略 宋体
        WriteCellStyle contentStyle = new WriteCellStyle();
        // 设置 垂直居中
        contentStyle.setWrapped(true);
        contentStyle.setVerticalAlignment(VerticalAlignment.CENTER);
        // 设置 水平靠左
        contentStyle.setHorizontalAlignment(HorizontalAlignment.LEFT);
        WriteFont contentWriteFont = new WriteFont();
        // 内容字号
        contentWriteFont.setFontHeightInPoints((short)12);
        // 字体样式
        contentWriteFont.setFontName("宋体");
        contentStyle.setWriteFont(contentWriteFont);
        // 这个策略是 头是头的样式 内容是内容的样式 其他的策略可以自己实现
        return new HorizontalCellStyleStrategy(headWriteCellStyle, contentStyle);
    }
}
